package com.ls.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.Texts;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.ls.domain.*;
import com.ls.domain.vo.InputReportScore;
import com.ls.domain.vo.ReportScore;
import com.ls.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.CellType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/report")
public class ReportController {

    @Autowired
    private StudentService studentService;
    @Autowired
    private TeacherService teacherService;
    @Autowired
    private ReportService reportService;
    @Autowired
    private AnswerService answerService;
    @Autowired
    private ScoreService scoreService;

    //===报告表    增删改查
    //管理员添加报告 实体（通过班级把学号和报告号添加到确认表）
    @PostMapping("/save")
    public boolean save(@RequestBody Report report) {
        String mClass = report.getReportClass();
        LambdaQueryWrapper<Student> studentLambdaQueryWrapper = new LambdaQueryWrapper<>();
        studentLambdaQueryWrapper.eq(Student::getStudentClass, mClass);
        List<Student> studentsExist = studentService.list(studentLambdaQueryWrapper);
        if (studentsExist.size() == 0) {
            return false;
        }
        reportService.save(report);
        Integer rid = report.getId();
        Answer as = new Answer();
        Score sc = new Score();
        List<Student> students = studentService.list(studentLambdaQueryWrapper);
        for (Student student : students) {
            Integer sid = student.getId();
            as.setRid(rid);
            sc.setRid(rid);
            as.setSid(sid);
            sc.setSid(sid);
            answerService.save(as);
            scoreService.save(sc);
        }
        return true;
    }

    //删除报告 id
    @DeleteMapping("/deleteById/{id}")
    public boolean deleteById(@PathVariable("id") Integer id) {
        return reportService.removeById(id);
    }

    //批量删除报告 ids
    @PostMapping("/deleteByIds")
    public boolean deleteByIds(@RequestBody List<Integer> ids) {
        return reportService.removeByIds(ids);
    }

    //更改报告 id
    @PutMapping("/update/{id}")
    public boolean update(@RequestBody Report report) {
        return reportService.updateById(report);
    }

    //查询报告 id
    @GetMapping("/selectById/{id}")
    public Report selectById(@PathVariable("id") Integer id) {
        return reportService.getById(id);
    }

    //管理员查询所有报告
    @GetMapping("/selectAll")
    public Map<String, Object> selectAll(int currentPage, int pageSize) {
        Page<Report> pageInfo = new Page<>(currentPage, pageSize);
        reportService.page(pageInfo);
        Map<String, Object> map = new HashMap<>();
        map.put("tableData", pageInfo.getRecords());
        map.put("totalCount", pageInfo.getTotal());
        return map;
    }

    //教师查询报告 用户班级
    @GetMapping("/selectAllTch")
    public Map<String, Object> selectAllTch(int currentPage, int pageSize, String teacherClass) {
        LambdaQueryWrapper<Report> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Report::getReportClass, teacherClass);
        Page<Report> pageInfo = new Page<>(currentPage, pageSize);
        reportService.page(pageInfo, queryWrapper);
        Map<String, Object> map = new HashMap<>();
        map.put("tableData", pageInfo.getRecords());
        map.put("totalCount", pageInfo.getTotal());
        return map;
    }

    //管理员搜索报告 实体
    @PostMapping("/selectByConditions")
    public Map<String, Object> selectByConditions(int currentPage, int pageSize, @RequestBody Report report) {
        LambdaQueryWrapper<Report> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Report::getReportName, report.getReportName())
                .like(Report::getReportClass, report.getReportClass());
        Page<Report> pageInfo = new Page<>(currentPage, pageSize);
        reportService.page(pageInfo, queryWrapper);
        Map<String, Object> map = new HashMap<>();
        map.put("tableData", pageInfo.getRecords());
        map.put("totalCount", pageInfo.getTotal());
        return map;
    }

    //教师搜索本班报告 实体、教师班级
    @PostMapping("/selectByConditionsTch")
    public Map<String, Object> selectByConditionsUser(int currentPage, int pageSize,@RequestBody Report report, String teacherClass) {
        LambdaQueryWrapper<Report> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Report::getReportName, report.getReportName())
                .eq(Report::getReportClass, teacherClass);
        Page<Report> pageInfo = new Page<>(currentPage, pageSize);
        reportService.page(pageInfo, queryWrapper);
        Map<String, Object> map = new HashMap<>();
        map.put("tableData", pageInfo.getRecords());
        map.put("totalCount", pageInfo.getTotal());
        return map;
    }

    //===答案表    改查
    //学生（保存功能）报告    实体
    @PutMapping("/saveStuAnswer")
    public boolean saveStu(@RequestBody Answer answer,Integer sid, Integer rid) {
        LambdaQueryWrapper<Answer> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Answer::getSid,sid)
                .eq(Answer::getRid,rid);
        Answer answer1 = answerService.getOne(queryWrapper);
        answer1.setReportAnswer(answer.getReportAnswer());
        return answerService.update(answer1,queryWrapper);
    }

    //学生提交报告 实体 与上面功能一样但是否完成改为1
    @PutMapping("/finishStuAnswer")
    public boolean inputStu(@RequestBody Answer answer,Integer sid, Integer rid) {
        LambdaQueryWrapper<Answer> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Answer::getSid,sid)
                .eq(Answer::getRid,rid);
        Answer answer1 = answerService.getOne(queryWrapper);
        answer1.setReportAnswer(answer.getReportAnswer());
        answer1.setAnswerFinish(1);
        return answerService.update(answer1,queryWrapper);
    }

    //答案id查询答案
    @GetMapping("/selectAnswerById")
    public Answer selectAnswer(Integer rid, Integer sid) {
        LambdaQueryWrapper<Answer> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Answer::getRid, rid)
                .eq(Answer::getSid, sid);
        return answerService.getOne(queryWrapper);
    }

    //学生查询本人报告学生 注解sql：sid、是否提交、当前页面、页面大小
    @GetMapping("/selectReportStu")
    public Map<String, Object> selectReportStu(Integer sid, int currentPage, int pageSize) {
        int startIndex = (currentPage - 1) * pageSize;
        List<Report> reportList = answerService.selectReportBySid(sid, startIndex, pageSize);
        int count = answerService.selectReportBySidCount(sid);
        Map<String, Object> map = new HashMap<>();
        map.put("tableData", reportList);
        map.put("totalCount", count);
        return map;
    }

    //学生搜索自己报告  注解sql：实体、sid、是否提交、当前页面、页面大小
    @GetMapping("/selectReportStuConditions")
    public Map<String, Object> selectReportStuConditions(Integer sid, String reportName,int currentPage, int pageSize) {
        int startIndex = (currentPage - 1) * pageSize;
        List<Report> reportList = answerService.selectReportBySidConditions(sid, reportName, startIndex, pageSize);
        int count = answerService.selectReportBySidConditionsCount(sid, reportName);
        Map<String, Object> map = new HashMap<>();
        map.put("tableData", reportList);
        map.put("totalCount", count);
        return map;
    }

    //===成绩表    改查
    //教师提交（修改）成绩    实体
    @PutMapping("/correctingScore")
    public boolean correctingScore(@RequestBody ReportScore reportScore, Integer sid, Integer rid) {
        System.out.println("====================================="+reportScore+"=========="+sid+","+rid);
        LambdaQueryWrapper<Score> scoreLambdaQueryWrapper = new LambdaQueryWrapper<>();
        scoreLambdaQueryWrapper.eq(Score::getSid,sid).eq(Score::getRid,rid);
        Score score = scoreService.getOne(scoreLambdaQueryWrapper);
        score.setScorePoints(reportScore.getScorePoints());
        score.setReportScore(reportScore.getReportScore());
        score.setScoreRemark(reportScore.getScoreRemark());
        score.setScoreComment(reportScore.getScoreComment());
        return scoreService.update(score,scoreLambdaQueryWrapper);
    }

    //学生查询自己成绩  注解sql：sid、当前页面、页面大小
    @GetMapping("/selectScoreStu")
    public Map<String, Object> selectScoreStu(Integer sid, int currentPage, int pageSize){
        int startIndex = (currentPage - 1) * pageSize;
        List<ReportScore> reportScoreList = scoreService.selectScoreStu(sid,startIndex,pageSize);
        int count = scoreService.selectScoreStuCount(sid);
        Map<String, Object> map = new HashMap<>();
        map.put("tableData", reportScoreList);
        map.put("totalCount", count);
        return map;
    }

    //学生搜索自己成绩  注解sql：实体、sid、当前页面、页面大小
    @GetMapping("/searchScoreStu")
    public Map<String, Object> searchScoreStu(Integer sid, String reportName, int currentPage, int pageSize){
        int startIndex = (currentPage - 1) * pageSize;
        List<ReportScore> reportScoreList = scoreService.searchScoreStu(sid,reportName,startIndex,pageSize);
        int count = scoreService.searchScoreStuCount(sid,reportName);
        Map<String, Object> map = new HashMap<>();
        map.put("tableData", reportScoreList);
        map.put("totalCount", count);
        return map;
    }

    //教师查询学生完成的报告 注解sql：教师班级、当前页面、页面大小
    @GetMapping("/selectScoreTch")
    public Map<String, Object> selectScoreTch(String teacherClass, int currentPage, int pageSize){
        int startIndex = (currentPage - 1) * pageSize;
        List<ReportScore> reportScoreList = scoreService.selectScoreTch(teacherClass,startIndex,pageSize);
        int count = scoreService.selectScoreTchCount(teacherClass);
        Map<String, Object> map = new HashMap<>();
        map.put("tableData", reportScoreList);
        map.put("totalCount", count);
        return map;
    }

    //教师搜索学生完成的报告 注解sql：实体、教师班级、当前页面、页面大小
    @GetMapping("/searchScoreTch")
    public Map<String, Object> searchScoreTch(@RequestParam("teacherClass") String teacherClass,@RequestParam("reportName") String reportName,
                                              @RequestParam("sno") String sno,@RequestParam("studentName") String studentName,
                                              int currentPage, int pageSize){
        int startIndex = (currentPage - 1) * pageSize;
        List<ReportScore> reportScoreList = scoreService.searchScoreTch(teacherClass,reportName,sno,studentName,startIndex,pageSize);
        int count = scoreService.searchScoreTchCount(teacherClass,reportName,sno,studentName);
        Map<String, Object> map = new HashMap<>();
        map.put("tableData", reportScoreList);
        map.put("totalCount", count);
        return map;
    }

    //管理员查询报告
    @GetMapping("/selectScoreAdm")
    public Map<String, Object> selectScoreAdm(int currentPage, int pageSize){
        int startIndex = (currentPage - 1) * pageSize;
        List<ReportScore> reportScoreList = scoreService.selectScoreAdm(startIndex,pageSize);
        int count = scoreService.selectScoreAdmCount();
        Map<String, Object> map = new HashMap<>();
        map.put("tableData", reportScoreList);
        map.put("totalCount", count);
        return map;
    }

    //管理员搜索报告
    @GetMapping("/searchScoreAdm")
    public Map<String, Object> searchScoreAdm(String studentClass, String reportName, String sno, String studentName, int currentPage, int pageSize){
        int startIndex = (currentPage - 1) * pageSize;
        List<ReportScore> reportScoreList = scoreService.searchScoreAdm(studentClass,reportName,sno,studentName,startIndex,pageSize);
        int count = scoreService.searchScoreAdmCount(studentClass,reportName,sno,studentName);
        Map<String, Object> map = new HashMap<>();
        map.put("tableData", reportScoreList);
        map.put("totalCount", count);
        return map;
    }

    //教师端分析成绩
    @GetMapping("/analyseScoreTch")
    public List<Integer> analyseScoreTch(String teacherClass){
        List<String> scoreList = scoreService.analyseScoreTch(teacherClass);
        List<Integer> scoreChart = new ArrayList<>();
        int a = 0, b = 0, c = 0, d = 0, e = 0, count = 0;
        for (String score:scoreList) {
            if (score != null){
                int sc = Integer.parseInt(score);
                if (sc >= 0 && sc <=29){
                    a++;
                    count++;
                } else if (sc >= 30 && sc <=59){
                    b++;
                    count++;
                } else if (sc >= 60 && sc <=79){
                    c++;
                    count++;
                } else if (sc >= 80 && sc <=89){
                    d++;
                    count++;
                } else if (sc >= 90 && sc <=100){
                    e++;
                    count++;
                }
            }
        }
        scoreChart.add(a);
        scoreChart.add(b);
        scoreChart.add(c);
        scoreChart.add(d);
        scoreChart.add(e);
        scoreChart.add(count);
        System.out.println("========================="+scoreChart);
        return scoreChart;
    }

    //管理员端分析成绩
    @GetMapping("/analyseScoreAdm")
    public List<Integer> analyseScoreAdm(){
        List<Score> scoreList = scoreService.list();
        List<Integer> scoreChart = new ArrayList<>();
        int a = 0, b = 0, c = 0, d = 0, e = 0;
        int count = 0;
        for (Score score:scoreList) {
            if(score.getReportScore()!=null){
                int sc = Integer.parseInt(score.getReportScore());
                if (sc >= 0 && sc <=29){
                    a++;
                    count++;
                } else if (sc >= 30 && sc <=59){
                    b++;
                    count++;
                } else if (sc >= 60 && sc <=79){
                    c++;
                    count++;
                } else if (sc >= 80 && sc <=89){
                    d++;
                    count++;
                } else if (sc >= 90 && sc <=100){
                    e++;
                    count++;
                }
            }
        }
        scoreChart.add(a);
        scoreChart.add(b);
        scoreChart.add(c);
        scoreChart.add(d);
        scoreChart.add(e);
        scoreChart.add(count);
        System.out.println("========================="+scoreChart);
        return scoreChart;
    }

    //教师端导出成绩表
    @GetMapping("/exportTch")
    public void exportTch(HttpServletResponse response,@RequestParam("teacherClass") String teacherClass)  throws Exception{
        // 创建工作簿
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 创建sheet
        HSSFSheet sheet = workbook.createSheet("sheet1");
        sheet.setColumnWidth(0, 6000);
        sheet.setColumnWidth(1, 6000);
        sheet.setColumnWidth(2, 6000);
        sheet.setColumnWidth(3, 6000);
        sheet.setColumnWidth(4, 6000);
        sheet.setColumnWidth(5, 6000);
        // 设置表头字体样式
        HSSFFont columnHeadFont = workbook.createFont();
        columnHeadFont.setFontName("宋体");
        columnHeadFont.setFontHeightInPoints((short) 10);

        String fileName = "学生成绩单.xls"; // 设置要导出的文件的名字

        // 获取数据集合
        List<ReportScore> list = scoreService.inputScoreTch(teacherClass);
        // 生成标题行
        HSSFRow row = sheet.createRow(0);
        row.createCell(0).setCellValue("序号");
        row.createCell(1).setCellValue("学号");
        row.createCell(2).setCellValue("学生姓名");
        row.createCell(3).setCellValue("学生班级");
        row.createCell(4).setCellValue("实验名");
        row.createCell(5).setCellValue("成绩");

        ReportScore reportScore = new ReportScore();
        for (int i = 0; i < list.size(); i++) {
            reportScore = list.get(i);
            row = sheet.createRow(i+1); // 从第2行开始填充数据
            // 序号
            row.createCell(0).setCellValue(String.valueOf(i+1));
            row.createCell(1, CellType.STRING).setCellValue(reportScore.getSno());
            row.createCell(2,CellType.STRING).setCellValue(reportScore.getStudentName());
            row.createCell(3,CellType.STRING).setCellValue(reportScore.getStudentClass());
            row.createCell(4,CellType.STRING).setCellValue(reportScore.getReportName());
            if (reportScore.getReportScore() != null){
                row.createCell(5,CellType.STRING).setCellValue(reportScore.getReportScore());
            } else {
                row.createCell(5,CellType.STRING).setCellValue("未批改");
            }
        }
        response.setContentType("application/octet-stream");
        response.setHeader("Content-disposition",
                "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        response.flushBuffer();
        workbook.write(response.getOutputStream());
    }

    //管理员端导出成绩表
    @GetMapping("/exportAdm")
    public void exportAdm(HttpServletResponse response)  throws Exception{
        // 创建工作簿
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 创建sheet
        HSSFSheet sheet = workbook.createSheet("sheet1");
        sheet.setColumnWidth(0, 6000);
        sheet.setColumnWidth(1, 6000);
        sheet.setColumnWidth(2, 6000);
        sheet.setColumnWidth(3, 6000);
        sheet.setColumnWidth(4, 6000);
        sheet.setColumnWidth(5, 6000);
        // 设置表头字体样式
        HSSFFont columnHeadFont = workbook.createFont();
        columnHeadFont.setFontName("宋体");
        columnHeadFont.setFontHeightInPoints((short) 10);
        // 获取数据集合
        List<ReportScore> list = scoreService.inputScoreAdm();
        String fileName = "学生成绩单.xls"; // 设置要导出的文件的名字
        // 生成标题行
        HSSFRow row = sheet.createRow(0);
        row.createCell(0).setCellValue("序号");
        row.createCell(1).setCellValue("学号");
        row.createCell(2).setCellValue("学生姓名");
        row.createCell(3).setCellValue("学生班级");
        row.createCell(4).setCellValue("实验名");
        row.createCell(5).setCellValue("成绩");

        ReportScore reportScore = new ReportScore();
        for (int i = 0; i < list.size(); i++) {
            reportScore = list.get(i);
            row = sheet.createRow(i+1); // 从第2行开始填充数据
            // 序号
            row.createCell(0).setCellValue(String.valueOf(i+1));
            row.createCell(1, CellType.STRING).setCellValue(reportScore.getSno());
            row.createCell(2,CellType.STRING).setCellValue(reportScore.getStudentName());
            row.createCell(3,CellType.STRING).setCellValue(reportScore.getStudentClass());
            row.createCell(4,CellType.STRING).setCellValue(reportScore.getReportName());
            if (reportScore.getReportScore() != null){
                row.createCell(5,CellType.STRING).setCellValue(reportScore.getReportScore());
            } else {
                row.createCell(5,CellType.STRING).setCellValue("未批改");
            }
        }
        response.setContentType("application/octet-stream");
        response.setHeader("Content-disposition",
                "attachment;filename=" + java.net.URLEncoder.encode(fileName, "UTF-8"));
        response.flushBuffer();
        workbook.write(response.getOutputStream());
    }

    //导出报告为word
    @GetMapping("/reportInput")
    public boolean reportInput(HttpServletRequest request, HttpServletResponse response, Integer sid, Integer rid) throws IOException {
        //存放要填充的数据
        Map<String, Object> datas = new HashMap<String, Object>();
        String templateFilePath  = "D:/Desktop/Downloads/reportDemo.docx";
        String destFilePath  =  "D:/Desktop/Downloads/";
        ReportScore reportScore = scoreService.reportInput(sid,rid);
        datas.put("reportName", Texts.of(reportScore.getReportName()).create());
        datas.put("studentName", Texts.of(reportScore.getStudentName()).create());
        datas.put("studentClass", Texts.of(reportScore.getStudentClass()).create());
        datas.put("sno", Texts.of(reportScore.getSno()).create());
        String[] questions = reportScore.getReportQuestion().split(";");
        String[] answers = reportScore.getReportAnswer().split(";");
        List<InputReportScore> inputReportScoreList = new ArrayList<>();
        for (int i = 0; i < answers.length; i++) {
            if (questions[i] != null){
                InputReportScore irs = new InputReportScore();
                irs.setIndex(String.valueOf(i + 1));
                irs.setQuestion(questions[i]);
                irs.setAnswer(answers[i]);
                inputReportScoreList.add(irs);
            }
        }
        datas.put("lists", inputReportScoreList);
        // 插件列表,可以去官网查看，有列循环，还有行循环，这里是行循环实例
        LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
        //这里可以指定一个config类，用来指定一些规则，也可以改变模板中{{}}的这种格式
        Configure config = Configure.builder().bind("lists", policy).build();
        //渲染文件
        XWPFTemplate compile = XWPFTemplate.compile(templateFilePath, config);
        compile.render(datas);
        //输出为文件，指定输出文件名
        compile.writeToFile(destFilePath + reportScore.getStudentClass()
                + "-" + reportScore.getStudentName()
                + "-" + reportScore.getSno() + ".docx");
        return true;
    }

    //批量导出报告为word
    @PostMapping("/reportsInput")
    public boolean reportsInput(HttpServletRequest request, HttpServletResponse response,@RequestBody List<Integer> List,@RequestParam int ridSize) throws IOException {
        String templateFilePath  = "D:/Desktop/Downloads/reportDemo.docx";
        String destFilePath  =  "D:/Desktop/Downloads/";
        for (int i = 0; i < ridSize; i++){
            //存放要填充的数据
            Map<String, Object> datas = new HashMap<String, Object>();
            ReportScore reportScore = scoreService.reportInput(List.get(i+ridSize),List.get(i));
            datas.put("reportName", Texts.of(reportScore.getReportName()).create());
            datas.put("studentName", Texts.of(reportScore.getStudentName()).create());
            datas.put("studentClass", Texts.of(reportScore.getStudentClass()).create());
            datas.put("sno", Texts.of(reportScore.getSno()).create());
            String[] questions = reportScore.getReportQuestion().split(";");
            String[] answers = reportScore.getReportAnswer().split(";");
            List<InputReportScore> inputReportScoreList = new ArrayList<>();
            for (int f = 0; f < answers.length; f++) {
                if (questions[f] != null){
                    InputReportScore irs = new InputReportScore();
                    irs.setIndex(String.valueOf(f + 1));
                    irs.setQuestion(questions[f]);
                    irs.setAnswer(answers[f]);
                    inputReportScoreList.add(irs);
                }
            }
            datas.put("lists", inputReportScoreList);
            // 插件列表,可以去官网查看，有列循环，还有行循环，这里是行循环实例
            LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
            //这里可以指定一个config类，用来指定一些规则，也可以改变模板中{{}}的这种格式
            Configure config = Configure.builder().bind("lists", policy).build();
            //渲染文件
            XWPFTemplate compile = XWPFTemplate.compile(templateFilePath, config);
            compile.render(datas);
            //输出为文件，指定输出文件名
            compile.writeToFile(destFilePath + reportScore.getStudentClass()
                    + "-" + reportScore.getStudentName()
                    + "-" + reportScore.getSno() + ".docx");
        }

        return true;
    }
}
